home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’97
/
TempoHelper
/
source code
/
TempoHelper.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-06-28
|
10KB
|
405 lines
/* File: ASM.c */
#include <Errors.h>
#include <SetUpA4.h>
#include <A4Stuff.h>
#include <Icons.h>
#include "iconsextra.h"
#define ICON_SUCCESS 1025
#define ICON_FAILURE 1026
#define MyMenuID -16509
#define MyIconFamilyID 1024
// Special Undocumented Routines for System Mode
pascal OSErr TurnSystemModeOn(void) = {0x3F3C, 0x0040, 0xA88F};
pascal OSErr TurnSystemModeOff(void) = {0x3F3C, 0x0041, 0xA88F};
long gSystemMenuAddress;
long gDrawMenuBarAddress;
long gMenuSelectAddress;
long gMenuKeyAddress;
long gSetItemAddress;
long gInsertMenuAddress;
FSSpec gInitFSSpec; /* An FSSpec to this file (so we can get at it later) */
MenuHandle gMenuHandle; /* Our menu, as skanky as it is */
Handle gIconSuite; /* The icon suite for the title of our menu */
MenuHandle gHelpMenu;
Boolean gMenuInstalled; /* Have we set up our menu yet? */
// prototypes
typedef pascal void (*DrawMenuBarProcPtr) ();
#define callDrawMenuBar(userRoutine) \
(*(DrawMenuBarProcPtr)(userRoutine))()
typedef pascal long (*MenuSelectProcPtr) (Point startPt);
#define callMenuSelect(userRoutine, startPt) \
(*(MenuSelectProcPtr)(userRoutine))((startPt))
typedef pascal long (*MenuKeyProcPtr) (short ch);
#define callMenuKey(userRoutine, ch) \
(*(MenuKeyProcPtr)(userRoutine))((ch))
typedef pascal void (*SystemMenuProcPtr) (long menuResult);
#define callSystemMenu(userRoutine, menuResult) \
(*(SystemMenuProcPtr)(userRoutine))((menuResult))
typedef pascal void (*SetMenuItemProcPtr) (MenuRef menuH, short item, ConstStr255Param itemString);
#define callSetMenuItemText(userRoutine, menuH, item, itemString) \
(*(SetMenuItemProcPtr)(userRoutine))((menuH), (item), (itemString))
typedef pascal void (*InsertMenuProcPtr) (MenuRef menuH, short beforeID);
#define callInsertMenu(userRoutine, menuH, beforeID) \
(*(InsertMenuProcPtr)(userRoutine))((menuH), (beforeID))
extern pascal void ShowIcon7( short iconId, Boolean advance );
static OSErr GetFileFromRefNum (short fRefNum, short *volID, long *dirID, StringPtr name);
pascal void MyDrawMenuBar(void);
pascal void MySystemMenu(long MenuCode);
pascal long MyMenuSelect(Point startPt);
pascal long MyMenuKey(short theChar);
pascal long MyMenuKey(short theChar);
pascal void MySetMenuItemText(MenuRef theMenu, short item, ConstStr255Param itemString);
pascal void MyInsertMenu(MenuRef theMenu, short beforeID);
pascal void main()
{
Handle initHandle;
THz currZone;
Handle oneIcon;
short iconNum;
OSErr err;
EnterCodeResource();
PrepareCallback(); // setup a4 for later usage!
/* Locate this resource in memory and detach it */
initHandle = Get1Resource('INIT', 1024);
HNoPurge(initHandle);
DetachResource(initHandle);
err = GetFileFromRefNum(CurResFile(), &gInitFSSpec.vRefNum, &gInitFSSpec.parID, gInitFSSpec.name);
if (err) { /*Debugger();*/ goto done; } /* <<< If we display an icon, this should indicate a failure */
/*
Install the trap patches
*/
gDrawMenuBarAddress = (long)NGetTrapAddress(_DrawMenuBar, ToolTrap);
NSetTrapAddress((UniversalProcPtr)MyDrawMenuBar, _DrawMenuBar, ToolTrap);
gSystemMenuAddress = (long)NGetTrapAddress(_SystemMenu, ToolTrap);
NSetTrapAddress((UniversalProcPtr)MySystemMenu, _SystemMenu, ToolTrap);
gMenuSelectAddress = (long)NGetTrapAddress(_MenuSelect, ToolTrap);
NSetTrapAddress((UniversalProcPtr)MyMenuSelect, _MenuSelect, ToolTrap);
gMenuKeyAddress = (long)NGetTrapAddress(_MenuKey, ToolTrap);
NSetTrapAddress((UniversalProcPtr)MyMenuKey, _MenuKey, ToolTrap);
gSetItemAddress = (long)NGetTrapAddress(_SetItem, ToolTrap);
NSetTrapAddress((UniversalProcPtr)MySetMenuItemText, _SetItem, ToolTrap);
gInsertMenuAddress = (long)NGetTrapAddress(_InsertMenu, ToolTrap);
NSetTrapAddress((UniversalProcPtr)MyInsertMenu, _InsertMenu, ToolTrap);
currZone = GetZone();
SetZone(SystemZone());
gMenuHandle = NewMenu(MyMenuID, "\pxyzzy");
// load the icon suite and then detach all entries
if (GetIconSuite(&gIconSuite, MyIconFamilyID, svAllAvailableData) == noErr) {
HLock(gIconSuite);
for (iconNum = largeIcon1; iconNum <= miniIcon8; iconNum++) {
oneIcon = (**((IconSuiteHandle)gIconSuite)).table[iconNum];
if (oneIcon) DetachResource(oneIcon);
}
HUnlock(gIconSuite);
BlockMoveData(&gIconSuite, &(**gMenuHandle).menuData[2], 4);
(**gMenuHandle).menuData[1] = ~(**gMenuHandle).menuData[1] & 1;
}
SetZone(currZone);
gMenuInstalled = FALSE;
done:
ShowIcon7( (!err ? ICON_SUCCESS : ICON_FAILURE), TRUE );
ExitCodeResource();
}
static asm void saveregisters (void)
{
move.l (sp)+,a0 // the return address in a0
movem.l d0-d2/a1,-(sp) // which is not saved
jmp (a0)
}
static asm void restoreregisters (void)
{
move.l (sp)+,a0 // the return address in a0
movem.l (sp)+,d0-d2/a1 // which is not restored
jmp (a0)
}
pascal void MyDrawMenuBar(void)
{
long patchAddress;
EnterCallback();
saveregisters();
patchAddress = gDrawMenuBarAddress;
/* Install and/or update the menu */
if (gMenuHandle) {
OSErr err = noErr;
MenuHandle mh;
short i, ch;
Str255 itemStr;
// delete the old
for (i=CountMItems(gMenuHandle);i>=1;i--) { DeleteMenuItem(gMenuHandle, i); }
// append the new!
err = HMGetHelpMenuHandle(&mh);
if (!err && mh) {
for(i=1;i<=CountMItems(mh);i++) {
GetMenuItemText(mh, i, itemStr);
AppendMenu(gMenuHandle, "\p ");
SetMenuItemText(gMenuHandle, i, itemStr);
GetItemCmd(mh, i, &ch);
SetItemCmd(gMenuHandle, i, ch);
}
DeleteMenu((*mh)->menuID);
// Remember, the memory for mh is still around, just not in the menu.
InsertMenu(mh, hierMenu);
gHelpMenu = mh;
}
if (!gMenuInstalled) {
InsertMenu(gMenuHandle, 0);
gMenuInstalled = true;
}
}
patchDone:
restoreregisters();
ExitCallback();
callDrawMenuBar(patchAddress);
}
pascal long MyMenuSelect(Point startPt)
{
long patchAddress;
long menuResult;
short menuID, itemID;
EnterCallback();
saveregisters();
// Debugger();
patchAddress = gMenuSelectAddress;
menuResult = callMenuSelect(patchAddress, startPt);
menuID = HiWord(menuResult); itemID = LoWord(menuResult);
if (menuID == MyMenuID) // switch to real help menu!
menuResult = ((long)kHMHelpMenuID << 16) + itemID;
msdone:
restoreregisters();
ExitCallback();
return(menuResult);
}
pascal long MyMenuKey(short theChar)
{
long patchAddress;
long menuResult;
short menuID, itemID;
EnterCallback();
saveregisters();
// Debugger();
patchAddress = gMenuKeyAddress;
menuResult = callMenuKey(patchAddress, theChar);
menuID = HiWord(menuResult); itemID = LoWord(menuResult);
if (menuID == MyMenuID) // switch to real help menu!
menuResult = ((long)kHMHelpMenuID << 16) + itemID;
mkdone:
restoreregisters();
ExitCallback();
return(menuResult);
}
/* This gets called when the user selects one of the items in a system menu */
pascal void MySystemMenu(long menuCode)
{
long patchAddress;
short menuID = HiWord(menuCode), itemID = LoWord(menuCode);
EnterCallback();
saveregisters();
// save it off, if we need it!
patchAddress = gSystemMenuAddress;
// Debugger();
if (gMenuHandle) {
if (menuID == MyMenuID) { /* my menu was selected */
menuCode = ((long)kHMHelpMenuID << 16) + itemID;
}
}
smdone:
restoreregisters();
ExitCallback();
callSystemMenu(patchAddress, menuCode);
}
pascal void MySetMenuItemText(MenuRef theMenu, short item, ConstStr255Param itemString)
{
OSErr err = noErr;
long patchAddress;
MenuRef hMenu;
EnterCallback();
saveregisters();
// save it off, if we need it!
patchAddress = gSetItemAddress;
// err = HMGetHelpMenuHandle(&hMenu);
hMenu = gHelpMenu;
if (gMenuHandle && hMenu && (theMenu == hMenu) && (item <= CountMItems(gMenuHandle))) {
// Debugger();
// SetMenuItemText(gMenuHandle, item, itemString); // set our item too!
theMenu = gMenuHandle;
}
smidone:
restoreregisters();
ExitCallback();
callSetMenuItemText(patchAddress, theMenu, item, itemString);
}
pascal void MyInsertMenu(MenuRef theMenu, short beforeID)
{
OSErr err = noErr;
long patchAddress;
MenuRef hMenu;
EnterCallback();
saveregisters();
// save it off, if we need it!
patchAddress = gInsertMenuAddress;
err = HMGetHelpMenuHandle(&hMenu);
if (gMenuHandle && hMenu && (theMenu == hMenu)) {
Debugger();
beforeID = hierMenu; // get it out of main menu bar!
}
smidone:
restoreregisters();
ExitCallback();
callInsertMenu(patchAddress, theMenu, beforeID);
}
/* Determine if a given trap exists */
static Boolean TrapAvailable(long trapNum)
{
#define UNIMPL_TRAP 0xA89F
long trap1, trap2;
long numTraps;
short trapType;
/*
First, find out how big the trap table is. It will vary on
different machines. We assume that the trap InitGraf will always
be implemented.
*/
trap1 = (long)NGetTrapAddress(0xAA6E, ToolTrap);
trap2 = (long)NGetTrapAddress(0xA86E, ToolTrap);
if (trap1 == trap2)
numTraps = 0x200;
else
numTraps = 0x400;
/*
Now, figure out what kind of trap this is, so the client
doesn't have to worry about it.
*/
if ((trapNum & 0x0800) > 0)
trapType = ToolTrap;
else
trapType = OSTrap;
/*
Now, there are no tool box traps after a certain number,
so we can rule those out now.
*/
if (trapType == ToolTrap) {
trapNum &= 0x07FF;
if (trapNum >= numTraps)
trapNum = UNIMPL_TRAP;
}
/* Now, compare the trap address to the unimplemented trap address. */
trap1 = (long)NGetTrapAddress(trapNum, trapType);
trap2 = (long)NGetTrapAddress(UNIMPL_TRAP, ToolTrap);
if (trap1 == trap2)
return(FALSE);
else
return(TRUE);
}
static OSErr GetFileFromRefNum (short fRefNum, short *volID, long *dirID, StringPtr name)
{
OSErr err;
FCBPBPtr fcbInfoPtr;
fcbInfoPtr = (void*)NewPtrSysClear(sizeof(FCBPBRec));
if (!(err = MemError())) {
fcbInfoPtr->ioRefNum = fRefNum;
fcbInfoPtr->ioNamePtr = name;
err = PBGetFCBInfoSync(fcbInfoPtr);
if (!err) {
*volID = fcbInfoPtr->ioVRefNum;
if (*volID == 0) *volID = 0xFFFF; // means the system disk!
*dirID = fcbInfoPtr->ioFCBParID;
}
}
DisposePtr((Ptr)fcbInfoPtr);
return err;
}